package com.wen.Part6.DataStructure;

import java.io.File;
import java.util.*;

/**
*@Description: 邻接矩阵
*@date: 2021/7/11 11:04
**/
public class AdjacencyMatrix implements Graph {
    private int[][] matrix;
    private Map<String, Integer> key2Index = new HashMap<>();  // key转换为index
    private Map<Integer, String> index2Key = new HashMap<>();  // index转换为key
    private int size = 0;
    private double factor = 2;
    private int capacity;
    private int edgeSize;


    @Override
    public void add(int i, int j) {
        add(i,j,1);
    }


    // 使矩阵可以自动扩增
    @Override
    public void add(int i, int j, int weigth) {
        int newCapacity = this.capacity;
        while (i >= newCapacity || j >= newCapacity){
            newCapacity = (int)(factor*newCapacity);
        }
        int[][] newMatrix = new int[newCapacity][newCapacity];
        for (int k = 0; k < this.capacity; k++) {
            for (int l = 0; l < this.capacity; l++) {
                newMatrix[k][l] = matrix[k][l];
            }
        }
        matrix = newMatrix;
        this.capacity = newCapacity;
        if (matrix[i][j] == 0){this.edgeSize++;} //这个边原来不存在，边记录数加一
        matrix[i][j] = weigth;
    }

    public AdjacencyMatrix(int n) {
        this.capacity = n;
        this.matrix = new int[capacity][capacity];
    }

    public AdjacencyMatrix(File file){
        this.capacity = 10;
        this.matrix = new int[capacity][capacity];
        this.init(file);;
    }



    @Override
    public int key2Index(String key) {
        if (key2Index.containsKey(key)){
            return key2Index.get(key);
        }
        key2Index.put(key,size);
        index2Key.put(size,key);
        return size++;
    }

    @Override
    public String index2Key(int index) {
        return index2Key.get(index);
    }

    @Override
    public int getInDegree(int i) {
        int sum = 0;
        for (int j = 0; j < size; j++) {
            if (matrix[j][i] != 0){
                sum++;
            }
        }
        return sum;
    }

    @Override
    public void init(File file) {
        this.size = 0;
        key2Index.clear();
        index2Key.clear();
        Graph.super.init(file);
    }

    @Override
    public int getOutDegree(int i) {
        int sum = 0;
        for (int j = 0; j < size; j++) {
            if (matrix[i][j] != 0){
                sum++;
            }
        }
        return sum;
    }



    @Override
    public int getSize() {
        return size;
    }

    @Override
    public int getEdgeSize() {
        return this.edgeSize;
    }

    @Override
    public List<Edge> getEdges() {
        List<Edge> list = new ArrayList<>();
        int s = 0;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (matrix[i][j] != 0){
                    list.add(new Edge(index2Key(i),index2Key(j),i,j,matrix[i][j],s++));
                }
            }
        }
        return list;
    }

    @Override
    public List<Integer> getAccessible(int i) {
        List<Integer> list = new ArrayList<>();
        for (int j = 0; j < size; j++) {
            if (matrix[i][j] != 0){
                list.add(j);
            }
        }
        return list;
    }

    @Override
    public List<Integer> getAccessibled(int i) {
        List<Integer> list = new ArrayList<>();
        for (int j = 0; j < size; j++) {
            if (matrix[j][i] != 0){
                list.add(j);
            }
        }
        return list;
    }

    @Override
    public int getWeight(int i, int j) {
        return matrix[i][j];
    }

    public void setUnOrder(){
        for (int i = 0; i < this.size; i++) {
            for (int j = 0; j < this.size; j++) {
                if (this.matrix[i][j] != 0){
                    this.matrix[j][i] = this.matrix[i][j];
                }
            }
        }
    }
}
